module CanCamel
  module Filter
    def self.included(base)
      base.define_singleton_method(:register_filter) { |*args| CanCamel::Filter.register_filter(*args) }
    end

    class <<self
      def register_filter(x, lambda = nil)
        case x
        when Class
          filter = x.new
        when Symbol
          begin
            filter = Filters::CustomFilter.new(x, lambda || method(x))
          rescue NameError
            raise ArgumentError, "no method #{x} defined and lambda not passed"
          end
        when Method
          filter = Filters::CustomFilter.new(x.name, x)
        else
          filter = x
        end

        raise ArgumentError, "#{x} is neither Filter nor Class nor Symbol nor Method" unless filter?(filter)
        filter.try(:validate!)
        filters[filter.name] = filter
      end

      def filters
        @filters ||= {}
      end

      private

      def filter?(x)
        %i(invoke! name).reduce { |a, e| a && x.respond_to?(e) }
      end
    end
  end
end
